package com.yiboshi.rehrs.manager;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yiboshi.rehrs.common.VarConstant;
import com.yiboshi.rehrs.config.ThreadLocalSession;
import com.yiboshi.rehrs.domain.entity.SystemConfig;
import com.yiboshi.rehrs.domain.entity.ZhongOrder;
import com.yiboshi.rehrs.domain.entity.ZhongUser;
import com.yiboshi.rehrs.domain.service.ISystemConfigService;
import com.yiboshi.rehrs.domain.service.IZhongOrderService;
import com.yiboshi.rehrs.domain.service.IZhongUserService;
import com.yiboshi.rehrs.exception.ZyantExceptionUtils;
import com.yiboshi.rehrs.helper.HttpHelper;
import com.yiboshi.rehrs.helper.RedisHelper;
import com.yiboshi.rehrs.helper.RedisLocker;
import com.yiboshi.rehrs.param.ZhongRes;
import com.yiboshi.rehrs.param.smurfs.PayInfo;
import com.yiboshi.rehrs.util.CacheUtils;
import com.yiboshi.rehrs.util.OkHttpUtil;
import com.yiboshi.rehrs.util.StrUtils;
import com.yiboshi.rehrs.util.ThreadPoolUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 蓝精灵
 */
@Component
@Slf4j
public class SmurfsManager {
   static  final String[] fields = {"waybillNo","receiverLinker","receiverAddr",
            "receiverMobile","waybillState","importRegionDate",
            "sender","senderAddr","senderMobile",
            "manOutCall","signFeedbackDate"};

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    ZhongYouManager zhongYouManager;
    @Autowired
    HttpHelper httpHelper;

    @Autowired
    ISystemConfigService systemConfigService;

    @Autowired
    IZhongOrderService zhongOrderService;
    @Autowired
    IZhongUserService zhongUserService;

    @Autowired
    RedisHelper redisHelper;

    @Autowired
    RedisLocker redisLocker;

    public String checkToken(String token)  {
        if(StrUtils.isBlank(token)){
            return "";
        }
        String key = "huotan:usells-logon-token-"+ token;
        String byCache10Min = CacheUtils.getByCache10Min(key, String.class);
        if(StrUtils.isNotBlank(byCache10Min)){
            return byCache10Min;
        }
        Map<String, String> headerMap = new HashedMap();
        headerMap.put("Content-Type", "application/x-www-form-urlencoded");
        headerMap.put("referer","https://usells.com/street");
        headerMap.put("origin","https://usells.com");
        headerMap.put("user-agent","Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36");
        headerMap.put("Cookie","vtoken="+token);
        String execute = new OkHttpUtil().url("https://usells.com/api/v2/user/info").retryCount(2)
                .get()
                .headers(headerMap).execute();
        String s1 = Optional.ofNullable(execute).map(s -> JSONObject.parseObject(s))
                .map(o -> o.getJSONObject("data"))
                .map(o -> o.getJSONObject("user"))
                .map(u -> u.getString("id"))
                .orElse("");
        if(StrUtils.isNotBlank(s1)){
            CacheUtils.putByCache10Min(key, s1);
        }else{
            //ZhongRes.fail("充值功能暂时关闭,请稍后再试-ERROR");
            ZyantExceptionUtils.e(true, "充值功能暂时关闭,请稍后再试-USRE");
        }
        return  s1;
    }

    public PayInfo payUrl(String oderCode, String payType){
        String api = "https://www.huotan.com/api/v2/payment/topay/%s?type=%s&r=2";
        api = String.format(api,oderCode,payType);
        PayInfo payInfo = new PayInfo();
        payInfo.setPayUrl(api);
        payInfo.setOrderCode(oderCode);

        return payInfo;
    }
    public String createOrder(String productId, String payType,String token)  {
        String userId = "30004";
        //获取cartHash
        Map<String, String> headerMap = new HashedMap();
        headerMap.put("Cookie","vtoken="+token);
        //添加购物车
        String execute1 = new OkHttpUtil().url("https://xiaoamao.usells.com/api/v2/cart/add")
                .timeoutMillis(2000)
                .retryCount(2)
                .post("version_id=0&product_id="+productId)
                .headers(headerMap).execute();
        JSONObject jsonObject1 = JSONObject.parseObject(execute1);
        String hash = Optional.ofNullable(jsonObject1).map(o -> o.getJSONObject("data"))
                .map(o -> o.getJSONObject("cart")).map(o -> o.getString("hash")).orElse("");

        //支付
        String execute2 = new OkHttpUtil().url("https://xiaoamao.usells.com/api/v2/payment/prepay/"+userId)
                .timeoutMillis(2000)
                .retryCount(2)
                .post("cart="+hash)
                .headers(headerMap).execute();
        log.info("prepay res: {}",execute2);
        String prepay_id = Optional.ofNullable(execute2).map(o -> JSONObject.parseObject(o))
                .map(o -> o.getJSONObject("data")).map(o -> o.getString("prepay_id")).orElse("");
        return prepay_id;

    }




    public String orderToken(boolean noCache)  {
        String key = "usells:logon-token";
        String token =noCache?"":stringRedisTemplate.opsForValue().get(key);
        if(StrUtils.isNotBlank(token)){
            return token;
        }
        SystemConfig huotanPayUser = systemConfigService.getOne("huotan_pay_user");
        String account = huotanPayUser.getConfigValue();
        String pwd = huotanPayUser.getOtherValue();
        Map<String, String> headerMap = new HashedMap();
        headerMap.put("Content-Type", "application/x-www-form-urlencoded");
        headerMap.put("referer","https://usells.com/street");
        headerMap.put("origin","https://usells.com");
        headerMap.put("user-agent","Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36");

        String execute = new OkHttpUtil().url("https://xiaoamao.usells.com/api/v2/auth/login").retryCount(2)
                .post("account="+account+"&password="+pwd+"&client=web")
                .headers(headerMap).execute();
        JSONObject jsonObject = JSONObject.parseObject(execute);
        Integer ret = jsonObject==null?null:jsonObject.getInteger("ret");
        JSONObject logonData = null;
        if(Objects.equals(ret,0)){
            logonData = jsonObject.getJSONObject("data");
            //stringRedisTemplate.opsForValue().set("xiaoamao.usells.logon",logonData.toJSONString());
        }else{
            log.info("xiaoamao.usells.com login error res:{}",jsonObject);
        }
        token = logonData.getString("token");
        stringRedisTemplate.opsForValue().set(key,token, 7, TimeUnit.DAYS);
        return token;

    }

    //主动加载
    public ZhongRes  findpdasignWaybillinfoNew(ZhongUser zhongUser,String waybillState){
        //waybillState a已下段
        //2 待投递
        //1 已妥投
        //0 未妥投
        JSONObject jsonObjectReq = new JSONObject();
        jsonObjectReq.put("waybillState", waybillState);
        jsonObjectReq.put("orderTag", 1);
        jsonObjectReq.put("queryType",0);
//        已下段数量：basedetailbizcount
//        待投递： basecount
//        已妥投：detailbizcount
//        未妥投： bizcount
        JSONObject jsonObjectRes = httpHelper.sendOriginPost("/delivery-app/p/delivery/pdataskquery/findpdasignwaybillinfonew.do", zhongUser, jsonObjectReq);
        String string = jsonObjectRes.getString("msg");
        if(!string.equals("成功")){
            return jsonObjectRes.toJavaObject(ZhongRes.class);
        }
        jsonObjectRes = jsonObjectRes.getJSONObject("obj");
        jsonObjectRes.remove("sum");
        jsonObjectRes.remove("pageNo");
        jsonObjectRes.remove("count");
        jsonObjectRes.remove("hasNextPage");
        jsonObjectRes.remove("helpflag");
        JSONArray jsonArray = jsonObjectRes.getJSONArray("list");
        List<JSONObject> result = new ArrayList<>(jsonArray.size()); // 预分配容量
        for (Object item : jsonArray) {
            Map<String, Object> originMap = ((JSONObject) item).getInnerMap();
            Map<String, Object> filtered = new HashMap<>(fields.length + 1, 1f);
            for (String key : fields) {
                filtered.put(key, originMap.get(key));
            }
            result.add(new JSONObject(filtered));
        }
        //
        result.sort((a, b) -> {
            //电联
            String manOutCall_a = a.getString("manOutCall");
            String manOutCall_b = b.getString("manOutCall");
            if (!manOutCall_a.equals(manOutCall_b)){
                return manOutCall_a.compareTo(manOutCall_b);
            }
            //下段时间
            // 多字段排序示例
            int dateCompare = b.getString("importRegionDate")
                    .compareTo(a.getString("importRegionDate"));
            if (dateCompare != 0) return dateCompare;
            //妥投
            String signFeedbackDate_a = a.getString("signFeedbackDate");
            String signFeedbackDate_b = b.getString("signFeedbackDate");

            if (!signFeedbackDate_a.equals(signFeedbackDate_b)){
                return signFeedbackDate_a.compareTo(signFeedbackDate_b);
            }
            return a.getString("waybillNo")
                    .compareTo(b.getString("waybillNo"));
        });
        jsonObjectRes.put("list",result);
//        已下段数量：basedetailbizcount
//        待投递： basecount
//        已妥投：detailbizcount
//        未妥投： bizcount
        //stringRedisTemplate.
       return ZhongRes.ok(jsonObjectRes);
       // return jsonObjectRes;

    }
    //waybillState a已下段
    //2 待投递
    //1 已妥投
    //0 未妥投
    public ZhongRes  findpdasignWaybillinfoNew(String waybillState) {
        ZhongUser smUserInfo = ThreadLocalSession.getSmUserInfo();
        if(smUserInfo==null){
            return VarConstant.need_login_res;
        }
        String account = smUserInfo.getAccount();
        String key = "sm:findpdasignWaybillinfoNew:"+ LocalDate.now()+":" +account;
        String redisCacheStr = (String)stringRedisTemplate.opsForHash().get(key, waybillState);
        try{
            ZhongRes zhongRes  = ThreadPoolUtils.submitCallback(() -> {
               return  findpdasignWaybillinfoNew(smUserInfo, waybillState);
            }).get(6, TimeUnit.SECONDS);
            if(zhongRes.isOK()){
                Object obj = zhongRes.getObj();
                if(obj!=null){
                    stringRedisTemplate.opsForHash().put(key, waybillState, obj.toString());
                }

            }
           return zhongRes;
        }catch (Exception e){
            log.info("smUserInfo:{}",smUserInfo.getAccount(),e);
            if(StrUtils.isNotBlank(redisCacheStr)){
                return ZhongRes.ok(redisCacheStr);
            }
            return ZhongRes.fail("查询异常，请稍后重试");
        }


        /*ThreadPoolUtils.submitTask(()->{
            ZhongRes zhongRes = findpdasignWaybillinfoNew(smUserInfo, waybillState);
            boolean ok = zhongRes.isOK();
            if(ok){
                String jsonString = (String)zhongRes.getObj();
                stringRedisTemplate.opsForHash().put(key, waybillState, jsonString);
            }

        });*/



    }


    public void updateOrderStatus(String orderCode, String sessionAccount) {
        boolean update = zhongOrderService.update(new LambdaUpdateWrapper<ZhongOrder>()
                .eq(ZhongOrder::getOrderCode, orderCode)
                .eq(ZhongOrder::getPayStatus, 0)
                .set(ZhongOrder::getUpdateTime, LocalDateTime.now())
                .set(ZhongOrder::getPayTime, LocalDateTime.now())
                //.set(ZhongOrder::getPayAccount, smUserInfo.getAccount())
                .set(ZhongOrder::getPayStatus, 1));
        if(update){
            redisHelper.delSmLoadSession("", sessionAccount);
            ZhongOrder zhongOrder = zhongOrderService.getOne(zhongOrderService.getQueryWrapper().eq(ZhongOrder::getOrderCode, orderCode));
            /*if(smUserInfo!=null&&!smUserInfo.getAccount().equals(zhongOrder.getPayAccount())){
                log.info("订单支付错误，order:{},payAccount:{},session account:{}",orderCode
                        ,zhongOrder.getPayAccount(),smUserInfo.getAccount());
                //报错
                throw new ZhongException("P10000","订单支付错误,请联系客服。order:"+orderCode);
            }*/
            //String account = smUserInfo.getAccount();
            ZhongUser zhongUser = zhongUserService.getSmOne(sessionAccount);
            LocalDateTime vipExpDate = zhongUser.getVipExpDate();
            if(vipExpDate.isBefore(LocalDateTime.now())){
                vipExpDate = LocalDateTime.now();
            }
            Integer vipDays = zhongOrder.getVipDays();
            zhongUser.setVipExpDate(vipExpDate.plusDays(vipDays));
            zhongUserService.updateById(zhongUser);
            redisHelper.delSmLoadSession("", sessionAccount);
        }
    }

    public boolean checkHuotanOrder(String orderCode){
        String execute = new OkHttpUtil().timeoutMillis(2000)

                .url("https://xiaoamao.usells.com/api/v2/order/status?pid=" + orderCode)
                .get().execute();
        Boolean paid = Optional.ofNullable(execute)
                .map(o -> JSONObject.parseObject(o))
                .map(o -> o.getJSONObject("data"))
                .map(o -> o.getBooleanValue("is_paid"))
                .orElse(false);
        return paid;
    }

    public boolean checkLdxpOrder(String orderCode){
        String postJSONStr = String.format("{\"trade_no\":\"%s\"}",orderCode);
        String execute = new OkHttpUtil().timeoutMillis(3000)
                .addHeader("Content-Type", "application/json")
                .addHeader("User-Agent","Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Mobile Safari/537.36")
                .addHeader("Referer", "https://pay.ldxp.cn/item/"+orderCode)
                .url("https://pay.ldxp.cn/shopApi/Pay/query")
                .post(postJSONStr)
                .execute();
        Boolean paid = Optional.ofNullable(execute)
                .map(o -> JSONObject.parseObject(o))
                .map(o -> o.getString("msg"))
                .map(s-> "success".equals(s))
                .orElse(false);
        return paid;
    }


    public void orderTask() {
        try{
            //不再设置
           // zhongOrderService.updateByJob();



            List<ZhongOrder> zhongOrders = zhongOrderService.listByJob();
            for (ZhongOrder zhongOrder : zhongOrders) {
                String orderCode = zhongOrder.getOrderCode();
                String key = "sm:order:"+orderCode;
                boolean success = false;
                try{
                    success = redisLocker.tryLock(key, 20);
                    if(!success){
                        continue;
                    }
                    boolean paid = checkLdxpOrder(orderCode);
                    if(paid){
                        updateOrderStatus(orderCode, zhongOrder.getPayAccount());
                    }else{
                        Integer checkCount = zhongOrder.getCheckCount();
                        zhongOrder.setCheckCount(checkCount+1);
                        zhongOrderService.updateById(zhongOrder);
                        log.info("订单未支付，order:{}",orderCode);
                    }
                }finally {
                    if(success){
                        redisLocker.delLock(key);
                    }
                }

            }
        }catch (Exception e){
            log.error("",e);
        }
    }
}
